#include "ComTimer.h"




TimerEvent timerArray[MAX_TIMER_NUM];
static struct epoll_event eventList[MAX_TIMER_NUM];
static int epollfd = -1;

static int ComCreatetimerfd(int mstimer , int repeat)
{
    struct itimerspec new_value;
    struct timespec now;
    int ret = clock_gettime(CLOCK_REALTIME, &now);
    if(-1 == ret)
    {
        COMLOG_ERROR_LOG("clock_gettime error\n");
        return -1;
    }
    //第一次执行定时回调的到期时间
    new_value.it_value.tv_sec = mstimer/1000 > 0 ? mstimer/1000 : 1; //mstimer/1000;
    new_value.it_value.tv_nsec = now.tv_nsec + (mstimer%1000)*1000*1000; 
    //间隔循环执行周期
    if(repeat)
    {
       
       new_value.it_interval.tv_sec = mstimer/1000;
       new_value.it_interval.tv_nsec = (mstimer%1000)*1000*1000;
       COMLOG_ERROR_LOG("add repeat timer %d %d\n", new_value.it_interval.tv_sec, new_value.it_interval.tv_nsec);
    }
    else
    {
       new_value.it_interval.tv_sec = 0;
       new_value.it_interval.tv_nsec = 0;     
    }
    int timefd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);  
    //param2 0相对时间 1绝对时间 param4 返回之前定时器设置的超时时间
    ret = timerfd_settime(timefd, 0, &new_value, NULL);
    if(-1 == ret)
         return -1;
    return timefd;
}


static int ComTimerEpollAdd(int fd)
{
    //添加事件
    struct epoll_event event =  {0};
    event.events = EPOLLIN|EPOLLET;
    event.data.fd = fd;
    if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) < 0)
    {
        COMLOG_ERROR_LOG("epoll add failed fd: %d \n", fd);
        return -1;
    }
    else
        COMLOG_ERROR_LOG("epoll fd : %d add successed\n", fd);
    return 0;
}


//>=0 成功返回定时器句柄
int ComTimerAdd(TimerCallback cb, int mstimer , int repeat, void *data)
{
      int ret = -1;
      if(-1 == epollfd)
      {
           epollfd = epoll_create(MAX_TIMER_NUM);
           if(epollfd < 0)
           {
               COMLOG_ERROR_LOG("epoll create failed\n");
               return -1;
           }
             
      }
      for(int i = 0; i < MAX_TIMER_NUM; i++)
      {
           if(timerArray[i].valid == 0)
            {
                if((ret = ComCreatetimerfd(mstimer, repeat)) >= 0)
                {
                     if(0 == ComTimerEpollAdd(ret))
                     {
                        COMLOG_ERROR_LOG("Timer %d ms add successed\n", mstimer);
                        timerArray[i].timerfd = ret;
                        timerArray[i].cb = cb;
                        timerArray[i].data = data;
                        timerArray[i].valid = 1;
                        return 0;
                     }
                     else
                     {
                        COMLOG_ERROR_LOG("add epoll failed\n");
                        return -1;
                     }
                } 
                else
                {
                     COMLOG_ERROR_LOG("create timer failed\n");
                     return -1;
                }
            } 
      }
      return -1;
}


//删除定时器
int ComTimerDel(int timerfd)
{
    close(timerfd);
    for(int i  = 0; i < MAX_TIMER_NUM; i++)
    {
       if(timerArray[i].timerfd == timerfd)
       {
          timerArray[i].valid = 0;
        //   free(timerArray[i].data);
        //   timerArray[i].data = NULL;
       }

    }
}


//定时器调度
int ComTimerSchedule()
{
     uint64_t exp = 0;
     ssize_t s = 0;
     if(-1== epollfd)
     { 
        COMLOG_ERROR_LOG("No add timer event\n");
        return -1;
     }
     int ret = epoll_wait(epollfd, eventList, MAX_TIMER_NUM, 30);
     if(ret < 0)
     {
         COMLOG_ERROR_LOG("epoll error\n");
         return -1;
     }
     else if(ret == 0)
         return 0;
     for(int i = 0; i < ret; i++)
     {
        if(eventList[i].events & EPOLLERR || (eventList[i].events & EPOLLHUP) || !(eventList[i].events & EPOLLIN))
        {
           COMLOG_ERROR_LOG("epoll error\n");
           close(eventList[i].data.fd);
           return -1;
        }
        //找到回调进行执行
        for(int j = 0; j < MAX_TIMER_NUM; j++)
        {
            if(eventList[i].data.fd == timerArray[j].timerfd && 1 == timerArray[j].valid)
                 {
                    s = read(timerArray[j].timerfd, &exp, sizeof(uint64_t)); //必须要读取此时间
                    timerArray[j].cb(timerArray[j].data);
                    return 1;
                 }
        }
     }
     return 0;

}

//关闭定时器
int ComTimerClose()
{
   for(int i = 0; i < MAX_TIMER_NUM; i++)
   {
        timerArray[i].valid = 0;
        close(eventList[i].data.fd);
        free(timerArray[i].data);
        timerArray[i].data = NULL;
   } 
    close(epollfd);
    epollfd = -1;
}


